package timing.ukulele.third.msgChannel.handle.impl;

import cn.hutool.core.collection.CollUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.google.common.base.Throwables;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.template.WxMpTemplateData;
import me.chanjar.weixin.mp.bean.template.WxMpTemplateMessage;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import timing.ukulele.third.dictionary.msg.MsgChannelType;
import timing.ukulele.third.msgChannel.handle.BaseHandler;
import timing.ukulele.third.msgChannel.model.RecallTaskInfo;
import timing.ukulele.third.msgChannel.model.SendTaskInfo;
import timing.ukulele.third.msgChannel.model.content.CommonContentParamModel;
import timing.ukulele.third.msgChannel.model.content.OfficialAccountsContentModel;
import timing.ukulele.third.msgChannel.param.HandleMessageBaseResponse;
import timing.ukulele.third.msgChannel.utils.AccountUtils;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

/**
 * @author zh
 * 微信服务号推送处理
 * https://developers.weixin.qq.com/doc/service/guide/product/template_message/Template_Message_Interface.html
 */
@Component
@Slf4j
public class OfficialAccountHandler extends BaseHandler {

    @Autowired
    private AccountUtils accountUtils;

    public OfficialAccountHandler() {
        channelCode = MsgChannelType.OFFICIAL_ACCOUNT.getCode();
    }

    @Override
    public HandleMessageBaseResponse send(SendTaskInfo taskInfo) {
        // 构造返回值
        HandleMessageBaseResponse result = new HandleMessageBaseResponse();
        try {
            // 获取微信公众号账号信息
            OfficialAccountsContentModel contentModel = (OfficialAccountsContentModel) taskInfo.getContentModel();
            WxMpService wxMpService = accountUtils.getAccountById(taskInfo.getSendAccountId(), WxMpService.class);
            // 请求发送消息
            WxMpTemplateMessage message = assembleReq(taskInfo.getReceiver(), contentModel);
            wxMpService.getTemplateMsgService().sendTemplateMsg(message);
            result.setHandleFlag(true);
        } catch (WxErrorException e) {
            log.error("OfficialAccountHandler#send fail:{},params:{}", e.getError().getErrorMsg(), JSON.toJSONString(taskInfo));
            result.setHandleFlag(false);
        } catch (Exception e) {
            log.error("OfficialAccountHandler#send fail:{},params:{}", Throwables.getStackTraceAsString(e), JSON.toJSONString(taskInfo));
            result.setHandleFlag(false);
        }
        return result;
    }

    /**
     * 组装发送模板信息参数
     * @param receiver 接收信息者
     * @param contentModel 消息下发参数
     */
    private WxMpTemplateMessage assembleReq(Set<String> receiver, OfficialAccountsContentModel contentModel) {
        return WxMpTemplateMessage.builder()
                // SendMessageDirectAction做了处理，所以这里只回有一条数据
                .toUser(CollUtil.getFirst(receiver.iterator()))
                .templateId(contentModel.getTemplateId())
                .url(contentModel.getUrl())
                .data(getWxMpTemplateData(contentModel.getParamList()))
                .miniProgram(new WxMpTemplateMessage.MiniProgram(contentModel.getMiniProgramId(), contentModel.getPath(), false))
                .build();
    }

    /**
     * 构建模板消息参数
     * @param param 模板参数
     * @return
     */
    private List<WxMpTemplateData> getWxMpTemplateData(String param) {
        List<CommonContentParamModel> paramList = JSONArray.parseArray(param, CommonContentParamModel.class);
        List<WxMpTemplateData> templateDataList = new ArrayList<>(paramList.size());
        paramList.forEach(item -> {
            WxMpTemplateData wxMpTemplateData = new WxMpTemplateData();
            wxMpTemplateData.setName(item.getKey());
            wxMpTemplateData.setValue(item.getValueData());
            templateDataList.add(wxMpTemplateData);
        });
        return templateDataList;
    }

    /**
     * 微信服务号消息 不支持撤回
     * @param recallTaskInfo
     */
    @Override
    public HandleMessageBaseResponse recall(RecallTaskInfo recallTaskInfo) {
        return HandleMessageBaseResponse.builder().handleFlag(true).build();
    }

}

